#include <QEventLoop>
#include <QTimer>
#include <QDateTime>
#include <QDebug>
#include "csyncbaseth.h"
#include "clogoper.h"
#include "cpublicdata.h"
#include "ctag.h"
#include "cclientdata.h"

CSyncBaseTh::CSyncBaseTh()
{
    m_bhread.store(false);
    m_bShouldStop = false;
    m_bTagChanged = true;
    m_bFrist = true;
    m_pLib = nullptr;
    m_pModule = nullptr;
    m_nTagTimeOut = (qint64)CPublicData::instance().m_stServerCfg.m_nTagTimeOut;
    initModule();
}

CSyncBaseTh::~CSyncBaseTh()
{
    threadStop();
    m_bShouldStop = true;
    if(m_pModule != nullptr)
    {
        delete m_pModule;
        m_pModule = nullptr;
    }
    if (m_pLib!=nullptr)
    {
        m_pLib->unload();
        delete m_pLib;
        m_pLib = nullptr;
    }
    quit();
    wait();
}

void CSyncBaseTh::initModule()
{
    QString sPath = QCoreApplication::applicationDirPath();
    QString libraryPath;
#ifdef WIN32
    // 在Windows环境下加载 SyncBase6RW.dll
    libraryPath = sPath+"/SyncBase6RW.dll";  // 设置库文件路径
#elif defined(__linux__) || defined(__unix__)
    // 在Linux环境下加载 libSyncBase6RW.so
    libraryPath = sPath + "/libSyncBase6RW.so";  // 设置库文件路径
#else
    return;
#endif
    m_pLib = new QLibrary(libraryPath);
    if (m_pLib->load())
    {
        m_lpGetModelPtr = (GETMODULEPTREX)m_pLib->resolve("getModulePtrEx");
        if (m_lpGetModelPtr != nullptr)
        {
            m_pModule = m_lpGetModelPtr();
        }
        if (m_pModule != nullptr)
        {
            m_pModule->setLogRet(CSyncBaseTh::addMsg);
            QString sIP = CPublicData::instance().m_stSyncBaseCfg.m_sIp;
            int nPort = CPublicData::instance().m_stSyncBaseCfg.m_nPort;
            QString sUserName = CPublicData::instance().m_stSyncBaseCfg.m_sUser;
            QString sPassWd = CPublicData::instance().m_stSyncBaseCfg.m_sPassWd;
            QString sDbName = CPublicData::instance().m_stSyncBaseCfg.m_sDbName;
            QJsonObject jsonObj;
            jsonObj["sIp"] = sIP;
            jsonObj["nPort"] = nPort;
            jsonObj["sUserName"] = sUserName;
            jsonObj["sPassWd"] = sPassWd;
            jsonObj["sDbName"] = sDbName;
            // 将 JSON 对象转换为字符串
            QJsonDocument jsonDoc(jsonObj);
            QString jsonString = jsonDoc.toJson(QJsonDocument::Indented); // 格式化输出
            m_pModule->setConfig(jsonString.toStdString());
            //生成日志
            SExecLog sDevExecLog;
            sDevExecLog.m_sDevName = A2T("SyncBase驱动");
            sDevExecLog.m_bExecResult = false;
            sDevExecLog.m_sDescription = A2T("驱动加载成功");
            sDevExecLog.m_nAlarmLevel = enWorkInfo;
            sDevExecLog.m_dLogTime = QDateTime::currentDateTime();
            CLogOper::instance().addMsg("", sDevExecLog);
        }
    }
    else
    {
        qDebug()<<A2T("加载SyncBase失败,原因:%1").arg(m_pLib->errorString());
        //生成日志
        SExecLog sDevExecLog;
        sDevExecLog.m_sDevName = A2T("SyncBase驱动");
        sDevExecLog.m_bExecResult = false;
        sDevExecLog.m_sDescription = A2T("加载SyncBase失败,原因:%1").arg(m_pLib->errorString());
        sDevExecLog.m_nAlarmLevel = enErr;
        sDevExecLog.m_dLogTime = QDateTime::currentDateTime();
        CLogOper::instance().addMsg("", sDevExecLog);
    }
}

void CSyncBaseTh::startModule()
{
    if (m_pModule != nullptr)
    {
        m_pModule->start();
        //生成日志
        SExecLog sDevExecLog;
        sDevExecLog.m_sDevName = A2T("SyncBase驱动");
        sDevExecLog.m_bExecResult = false;
        sDevExecLog.m_sDescription = A2T("启动SyncBase连接");
        sDevExecLog.m_nAlarmLevel = enWorkInfo;
        sDevExecLog.m_dLogTime = QDateTime::currentDateTime();
        CLogOper::instance().addMsg("", sDevExecLog);
    }
}

void CSyncBaseTh::endModule()
{
    if (m_pModule != nullptr)
    {
        m_pModule->stop();
        //生成日志
        SExecLog sDevExecLog;
        sDevExecLog.m_sDevName = A2T("SyncBase驱动");
        sDevExecLog.m_bExecResult = false;
        sDevExecLog.m_sDescription = A2T("停止SyncBase");
        sDevExecLog.m_nAlarmLevel = enWorkInfo;
        sDevExecLog.m_dLogTime = QDateTime::currentDateTime();
        CLogOper::instance().addMsg("", sDevExecLog);
    }
}

void CSyncBaseTh::writeTag()
{
    if (m_pModule == nullptr)
    {
        return;
    }

    QDateTime dtmNow = QDateTime::currentDateTime();
    for (auto itor = m_mapClient.constBegin(); itor != m_mapClient.constEnd(); itor++)
    {
        CClientData* pClient = itor.key();
        QVector<CTagData*> vecTag = itor.value();
        bool bConnectState = pClient->m_bState;
        for (int i = 0; i < vecTag.size(); i++)
        {
            CTagData *pTag = vecTag.value(i, nullptr);
            if (pTag == nullptr) continue;
            CTag tag(pTag->m_sTagName.toStdString(), pTag->m_nDataType);
            tag.setValue(pTag->value.dNum, dtmNow.toMSecsSinceEpoch());
            tag.dataSize = pTag->m_nDataSize;
            //客户端未知错误转为数据错误
            if (tag.quality == CTagData::Q_UNKOWN) tag.quality = CTagData::Q_DATAERR;
            //客户端断连改为超时
            if (bConnectState == false)
            {
                pTag->setQuality(CTagData::Q_TIMEOUT);
                tag.quality = CTagData::Q_TIMEOUT;
            }
            else
            {
                //判断最后一次更新时间
                QDateTime dtmTag = pTag->getDateTime();
                qint64 nSec = dtmTag.secsTo(dtmNow);
                if (nSec > m_nTagTimeOut)
                {
                    pTag->setQuality(CTagData::Q_TIMEOUT);
                    tag.quality = CTagData::Q_TIMEOUT;
                }
                else
                {
                    tag.quality = pTag->getQuality();
                }
            }
            m_pModule->setValue(pTag->m_sTagName.toStdString(), tag);
        }
    }
}

//void CSyncBaseTh::writeTag()
//{
//    if (m_pModule == nullptr)
//    {
//        return;
//    }
//    uint64_t nTimeStampNow = CTagData::getTimeStamp();
//    QMutexLocker locker(CPublicData::instance().m_pMutex);
//    for (int i = 0; i < CPublicData::instance().m_vecTag.size(); i++)
//    {
//        CTagData *pTag = CPublicData::instance().m_vecTag[i];
//        QString sAddr = pTag->m_sTagName;
//        CTag tag(sAddr.toStdString(), pTag->m_nDataType);
//        tag.setValue(pTag->value.dNum, nTimeStampNow);
//        pTag->dataSize = pTagHis->m_nDataSize;
//        tag.quality = pTag->m_nQuality;
//        m_pModule->setValue(sAddr.toStdString(),tag);
//    }
//}


void CSyncBaseTh::writeTagHisTory()
{
    //复制全局类历史测点
    QVector<CTagData*> vecHistory;
    {
        QMutexLocker locker(CPublicData::instance().m_pMutex);
        vecHistory = CPublicData::instance().m_vecTagHistory;
        CPublicData::instance().m_vecTagHistory.clear();
    }
    if (vecHistory.size() > 0)
    {
        VecStr vecAddr;
        VecPTag vecPTag;
        for (int i = 0; i < vecHistory.size(); i++)
        {
            CTagData* pTagHis = vecHistory.value(i);
            if (pTagHis == nullptr) continue;
            QString sAddr = pTagHis->m_sTagName;
            CTag* pTag = new CTag(sAddr.toStdString(), pTagHis->m_nDataType);
            pTag->setValue(pTagHis->value.dNum);
            pTag->timeStamp = pTagHis->m_nTimeStamp;
            pTag->dataSize = pTagHis->m_nDataSize;
            pTag->quality = pTagHis->m_nQuality;
            vecAddr.push_back(sAddr.toStdString());
            vecPTag.push_back(pTag);
            SAFE_DELETE(pTagHis);
        }
        m_pModule->setValuesHistory(vecAddr, vecPTag);
        vecHistory.clear();
    }
}

void CSyncBaseTh::addMsg(const char *message, int nLevel)
{
    //生成日志
    SExecLog sDevExecLog;
    sDevExecLog.m_sDevName = A2T("SyncBase驱动");
    sDevExecLog.m_bExecResult = false;
    sDevExecLog.m_sDescription = QString::fromStdString(message);
    sDevExecLog.m_nAlarmLevel = nLevel;
    sDevExecLog.m_dLogTime = QDateTime::currentDateTime();
    CLogOper::instance().addMsg("", sDevExecLog);
}

void CSyncBaseTh::addMsg(int nLevel, const QString &sMsg, QDateTime dtm)
{
    SExecLog sDevExecLog;
    sDevExecLog.m_sDevName = A2T("SyncBase驱动");
    sDevExecLog.m_bExecResult = false;
    sDevExecLog.m_sDescription = sMsg;
    sDevExecLog.m_nAlarmLevel = nLevel;
    sDevExecLog.m_dLogTime = dtm;
    CLogOper::instance().addMsg("", sDevExecLog);
}

void CSyncBaseTh::threadStart()
{
    QMutexLocker locker(&m_mutex);  // 使用QMutexLocker管理锁
    m_nTagTimeOut = (qint64)CPublicData::instance().m_stServerCfg.m_nTagTimeOut;
    if (!m_bhread.load())
    {
        if (m_bFrist)
        {
            startModule();
            start();
            m_bFrist = false;
            m_bhread.store(true);
        }
        else
        {
            startModule();
            m_bhread.store(true);
        }
    }
}

void CSyncBaseTh::threadStop()
{
    QMutexLocker locker(&m_mutex);  // 使用QMutexLocker管理锁
    if (m_bhread.load())
    {
        endModule();
        m_bhread.store(false);
    }
}

void CSyncBaseTh::run()
{
    while (!m_bShouldStop)
    {
        {
            QMutexLocker locker(&m_mutex);
            if (!m_bhread.load())
            {
                QEventLoop loop;
                QTimer::singleShot(50, &loop, SLOT(quit()));//一秒钟查询一下数据库
                loop.exec();
                continue;
            }

            //测点重载中，跳过等待测点修改完成
            int nTagState = CPublicData::instance().m_nClientTagReload;
            if (CPublicData::enTagReloading == nTagState)
            {
                addMsg(enWorkInfo, A2T("点表发生变化，正在重载"));
                QEventLoop loop;
                QTimer::singleShot(1000, &loop, SLOT(quit()));
                loop.exec();
                continue;
            }
            //程序初始化或点表重载
            else if (CPublicData::enTagUpDate == nTagState || m_bTagChanged == true)
            {
                if (m_pModule != nullptr)
                {
                    //首先先把SyncBase维护的所有测点清空
                    m_pModule->clear();
                    for(int i = 0; i < CPublicData::instance().m_vecTag.size(); i++)
                    {
                        m_pModule->addTag(CPublicData::instance().m_vecTag[i]->m_sTagName.toStdString(), CPublicData::instance().m_vecTag[i]->m_nDataType, 0);
                    }
                    CPublicData::instance().m_nClientTagReload = CPublicData::enTagNoChange;
                    if (CPublicData::enTagUpDate == nTagState)
                    {
                        addMsg(enWorkInfo, A2T("点表发生变化，重载完成"));
                    }
                    else
                    {
                        addMsg(enWorkInfo, A2T("点表加载完成"));
                        m_bTagChanged = false;
                    }
                    m_mapClient.clear();
                    //录入客户端测点
                    QMap<QString, CClientData*> mapClient;
                    {
                        QMutexLocker lockerPublic(CPublicData::instance().m_pMutex);
                        mapClient = CPublicData::instance().m_mapClient;
                    }
                    QMapIterator<QString, CClientData*> itor(mapClient);
                    while (itor.hasNext())
                    {
                        itor.next();
                        QVector<CTagData*> vecTag = itor.value()->m_vecTag;
                        m_mapClient.insert(itor.value(), vecTag);
                    }
                }
            }
        }
        //write
        writeTag();
        writeTagHisTory();
        QEventLoop loop;
        QTimer::singleShot(1000, &loop, SLOT(quit()));//一秒钟查询一下数据库
        loop.exec();
    }
}
